package element.synt;

import element.ast.AstNode;
import element.ast.PrimNode;
import element.ast.UopNode;
import element.base.Synt;
import element.base.TreeNode;
import element.base.Word;

//UnaryExp → PrimaryExp | Ident '(' [FuncRParams] ')' | UnaryOp UnaryExp
public class UnaryExp extends Synt {

    public AstNode toAst() {
        if (this.isConst()) {
            return new PrimNode(this.calcu());
        }
        TreeNode node0 = this.getNodes().get(0);
        if (node0 instanceof UnaryOp) {
            Word uop = ((UnaryOp) node0).findFirst();
            String op = uop.getContent();
            UnaryExp sonexp = (UnaryExp) this.getNodes().get(1);
            AstNode sonNode = sonexp.toAst();
            return new UopNode(op, sonNode);
        } else if (node0 instanceof PrimaryExp) {
            return ((PrimaryExp) node0).toAst();
        } else {
            return new PrimNode(this);
        }
    }

    public int calcu() {
        TreeNode node0 = this.getNodes().get(0);
        if (node0 instanceof UnaryOp) {
            Word uop = ((UnaryOp) node0).findFirst();
            String op = uop.getContent();
            UnaryExp sonexp = (UnaryExp) this.getNodes().get(1);
            int sonvalue = sonexp.calcu();
            if (op.equals("+")) {
                return sonvalue;
            } else if (op.equals("-")) {
                return -sonvalue;
            } else {
                if (sonvalue == 0) {
                    return 1;
                } else {
                    return 0;
                }
            }
        } else if (node0 instanceof PrimaryExp) {
            return ((PrimaryExp) node0).calcu();
        } else {
            System.out.println("calcu not const![func]");
            System.exit(0);
        }
        return 0;
    }

    public boolean isConst() {
        TreeNode node0 = this.getNodes().get(0);
        if (node0 instanceof UnaryOp) {
            UnaryExp sonexp = (UnaryExp) this.getNodes().get(1);
            return sonexp.isConst();
        } else if (node0 instanceof PrimaryExp) {
            return ((PrimaryExp) node0).isConst();
        } else {
            return false;
        }
    }
}
